#ifndef __fuzzy_controller_h_
#define __fuzzy_controller_h_
#include "adevs/adevs.h"
#include "io_type.h"
#include "controller.h"
#include "fuzzylite/FuzzyLite.h"

class FuzzyController: public Controller
{
	public:
		/// Constructor.
		FuzzyController();
		/// Internal transition function.
		void delta_int();
		/// External transition function.
		void delta_ext(double e, const adevs::Bag<IO_Type>& xb);
		/// Confluent transition function.
		void delta_conf(const adevs::Bag<IO_Type>& xb);
		/// Output function.  
		void output_func(adevs::Bag<IO_Type>& yb);
		/// Time advance function.
		double ta();
		/// Output value garbage collection.
		void gc_output(adevs::Bag<IO_Type>& g);
		/// Destructor.
		~FuzzyController();

	private:
		fl::FuzzyEngine* green_engine;
		fl::InputLVar* rateOfArival;
		fl::InputLVar* longestOnRed;
		fl::InputLVar* lengthOnGreen;
		fl::InputLVar* remainingGreen;
		fl::OutputLVar* green_change;

		void init_green_fuzzy();
		double get_green_increase(int length_on_green, double rate_of_arival, int longest_on_red, double remaining_green);

		fl::FuzzyEngine* side_engine;
		fl::InputLVar* side_longestOnRed;
		fl::InputLVar* side_rateOfArival;
		fl::InputLVar* side_queueLength;
		fl::InputLVar* side_skippedPhase;
		fl::OutputLVar* side_priority;

		void init_side_change_fuzzy();
		int get_next_side();
		double get_side_priority(int longest_on_red, int queue_length, int skipped_phases);

		int get_longest_on_red(int& side);

		double remaining_time;
		double total_time;
		int current_side_green;
		int next_side_green;
		int* sides_count;
		int arivals_during_green;
		int* phases_skipped;

};

#endif
